package com.bhf.core;

import com.bhf.annotation.OperationLog;
import com.bhf.model.entity.CustomUser;
import com.bhf.model.entity.UserOperationLog;
import com.bhf.task.AsyncTask;
import com.bhf.utils.IpAddressUtil;
import com.bhf.utils.RestResult;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;

/**
 * @author pwq
 */
@Aspect
@Component
public class OperationLogAspect {

    @Resource
    private AsyncTask asyncTask;

    /**
     * 设置操作日志切入点在注解的位置切入代码
     */
    @Pointcut(value = "@annotation(com.bhf.annotation.OperationLog)")
    public void operationLogCut() {
    }

    /**
     * 记录操作日志
     * @param joinPoint 方法的执行点
     * @param result  方法返回值
     * @throws Throwable
     */
    @AfterReturning(returning = "result",value = "operationLogCut()")
    public void saveOperationLog(JoinPoint joinPoint, RestResult<?> result) throws Throwable {
        UserOperationLog operationLog = new UserOperationLog();
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        operationLog.setIp(IpAddressUtil.getIpAdrress(request));
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        OperationLog annotation = signature.getMethod().getAnnotation(OperationLog.class);
        if (null != annotation){
            operationLog.setOperation(annotation.value());
        }
        operationLog.setMethodName(signature.getMethod().getName());
        String className = joinPoint.getTarget().getClass().getName();
        operationLog.setClassName(className);
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (!(authentication instanceof AnonymousAuthenticationToken)){
            CustomUser principal = (CustomUser) authentication.getPrincipal();
            operationLog.setUserId(principal.getId());
        }
        operationLog.setResult(result.getCode());
        asyncTask.insertUserOperationLog(operationLog);
    }
}
